#!/usr/bin/env bash

LAUNCHCTLPATHS=( \
    $HOME/Library/LaunchAgents \
    /Library/LaunchAgents \
    /Library/LaunchDaemons \
    /System/Library/LaunchAgents \
    /System/Library/LaunchDaemons \
    )

help(){
    cat<<__EOF__
Usage: m service [OPTIONS]

Description: Manage macOS services using launchctl

Options:
  --help              Show this help message and exit
  --list              List all services
  --info   SERVICE    Show information about a specific service
  --start  SERVICE    Start a service
  --stop   SERVICE    Stop a service
  --status SERVICE    Show status of a service
  --enable  SERVICE   Enable a service
  --disable SERVICE   Disable a service
__EOF__
}

find_service(){
    [ -z "$1" ] && help && exit 1

    for p in "${LAUNCHCTLPATHS[@]}"; do
        if [ -f "${p}/${1}" ]; then
            echo "${p}/${1}"
        elif [ -f "${p}/${1}.plist" ]; then
            echo "${p}/${1}.plist"
        fi
    done
}

service_info(){
    sudo launchctl list ${1}
}

service_status(){
    local service_name="${1}"
    if [ -z "${service_name}" ]; then
        help && exit 1
    fi
    printf "PID\tStatus\tLabel\n"
    service_info | grep $@
}

service_do(){
    local action="${1}"
    local service_name="${2}"
    if [ -z "${action}" ] || [ -z "${service_name}" ]; then
        help && exit 1
    fi
    local service_path=$(find_service "${service_name}")
    if [ -z "${service_path}" ]; then
        echo "Service path for '${service_name}' not found." 1>&2
        exit 1
    fi
    # local
    local override="-w"
    case "${action}" in
        # convert action to launchctl command
        enable)
            action="load" ;;
        disable)
            action="unload" ;;
        # override argument applies only to load/unload
        start)
            override="" ;;
        stop)
            override="" ;;
        *)
            help && exit 1
            ;;
        esac
        sudo launchctl "${action}" ${override} "${service_path}" 2>/dev/null
        echo "Service '${service_name}' ${action}ed"
}


option="${1}"
if [ -z "${option}" ]; then
    help && exit 1
fi

shift
case ${option} in
    --help)
        help
        ;;
    --info)
        service_info $@
        ;;
    --list)
        # if no arguments are given, list all services
        service_info
        ;;
    --enable)
        service_do enable $@
        ;;
    --disable)
        service_do disable $@
        ;;
    --start)
        service_do start $@
        ;;
    --stop)
        service_do stop $@
        ;;
    --status)
        service_status $@
        ;;
    *)
        help && exit 1
        ;;
esac
